﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using Microsoft.SharePoint;
using System.Xml;
using System.Collections;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Web.UI;

namespace beyCoo4Sharepoint
{
    class beyCooConnection
    {
        private static string sslErrors;
        
        /// <summary>
        /// convert the file that was uploaded to sharepoint to a base64 encoded string to be sent to the beyCoo webservice
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public string File2Base64(string url)
        {
            string encodedData = "";
            try
            {
                WebRequest webRequest = WebRequest.Create(url);
                webRequest.Credentials = CredentialCache.DefaultCredentials;
                webRequest.Method = "GET";
                WebResponse webResponse = webRequest.GetResponse();
                Stream remoteStream = webResponse.GetResponseStream();
                MemoryStream ms = new MemoryStream();
                byte[] buffer = new byte[1024];
                int bytes;
                
                while ((bytes = remoteStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, bytes);
                }
                byte[] output = ms.ToArray();
                encodedData = Convert.ToBase64String(output);    
            }
            catch (Exception Exc)
            {
                beyCooLogger.LogError("beyCooError", Exc.Message + Exc.StackTrace);             
            }
            return encodedData;
        }

        /// <summary>
        /// create a connection to the beyCoo webservice and get the beyCoo response doc
        /// </summary>
        /// <param name="url"></param>
        /// <param name="inhalt"></param>
        /// <param name="servername"></param>
        /// <returns></returns>
        public string Connection(string url, string inhalt, string servername)
        {
            using (SPSite site = new SPSite(servername))
            {
                using (SPWeb web = site.OpenWeb())
                {

                    byte[] bytes = Encoding.UTF8.GetBytes(inhalt);
                    StringBuilder sb = new StringBuilder();
                    byte[] buf = new byte[1024];


                    ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);

                    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
                    webRequest.PreAuthenticate = true;
                    webRequest.Method = "POST";
                    webRequest.ContentLength = bytes.Length;
                    if (web.Properties.ContainsKey(beyCooConstants.beyCooUseProxy))
                    {
                        bool useProxy = Boolean.Parse(web.Properties[beyCooConstants.beyCooUseProxy].ToString());
                        if (useProxy)
                        {
                            AddProxy(webRequest, web);
                        }
                    }
                    try
                    {
                        using (Stream requestStream = webRequest.GetRequestStream())
                        {
                            requestStream.Write(bytes, 0, bytes.Length);
                        }
                    }
                    catch (Exception Exc)
                    {
                        beyCooLogger.LogError("beyCooError", Exc.Message + Exc.StackTrace);
                    }

                    HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
                    if (webResponse.StatusCode != HttpStatusCode.OK)
                    {
                        //&RA:TODO
                        beyCooLogger.LogError("beyCooError", webResponse.StatusCode + webResponse.StatusDescription);
                    }
                    Stream newStream = webResponse.GetResponseStream();
                    string tempString = null;
                    int count = 0;

                    do
                    {
                        count = newStream.Read(buf, 0, buf.Length);

                        if (count != 0)
                        {
                            tempString = Encoding.UTF8.GetString(buf, 0, count);

                            sb.Append(tempString);
                        }
                    }

                    while (count > 0);

                    tempString = sb.ToString();
                    newStream.Close();
                    webResponse.Close();

                    return tempString;
                }
            }
        }

        /// <summary>
        /// Check if the server certificate is valid, when not, display popup to user
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="certificate"></param>
        /// <param name="chain"></param>
        /// <param name="sslPolicyErrors"></param>
        /// <returns></returns>
        public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            bool certMatch = false;
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                // Good certificate.
                sslErrors = "";
                return true;
            }
            else
            {
                beyCooLogger.LogError("beyCooError", "SSL certificate error: " + sslPolicyErrors.ToString());
                sslErrors = sslPolicyErrors.ToString();
                certMatch = true; //still continue, but notify user that certificate is not trusted
            }
            return certMatch;

        }

        public Hashtable getServices(string url, string servername)
        {
            Hashtable services = new Hashtable();
            using (SPSite site = new SPSite(servername))
            {
                using (SPWeb web = site.OpenWeb())
                {

                    //byte[] bytes = Encoding.UTF8.GetBytes(inhalt);
                    StringBuilder sb = new StringBuilder();
                    byte[] buf = new byte[1024];

                    ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
                    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
                    webRequest.Credentials = CredentialCache.DefaultCredentials;
                    webRequest.Method = "GET";

                    if (web.Properties.ContainsKey(beyCooConstants.beyCooUseProxy))
                    {
                        bool useProxy = Boolean.Parse(web.Properties[beyCooConstants.beyCooUseProxy].ToString());
                        if (useProxy)
                        {
                            AddProxy(webRequest, web);
                        }
                    }

                    try
                    {
                        HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
                        
                        if (webResponse.StatusCode != HttpStatusCode.OK)
                        {
                            //&RA:TODO
                            beyCooLogger.LogMessage("beyCooMessage", webResponse.StatusCode + webResponse.StatusDescription);
                        }
                        Stream newStream = webResponse.GetResponseStream();
                        string tempString = null;
                        int count = 0;

                        do
                        {
                            count = newStream.Read(buf, 0, buf.Length);

                            if (count != 0)
                            {
                                tempString = Encoding.UTF8.GetString(buf, 0, count);

                                sb.Append(tempString);
                            }
                        }

                        while (count > 0);

                        tempString = sb.ToString();
                        newStream.Close();
                        webResponse.Close();


                        //save the available services to hash                        
                        XmlDocument resultDoc = new XmlDocument();
                        resultDoc.LoadXml(sb.ToString());
                        XmlNode root = resultDoc.DocumentElement;

                        string xpathSelectServices = "/beycoo/customer/services/service";

                        XmlNodeList nodeList = root.SelectNodes(xpathSelectServices);
                        foreach (XmlNode node in nodeList)
                        {
                            services.Add(node.Attributes["name"].Value, node.Attributes["service-type"].Value + "|" + node.Attributes["service-key"].Value);
                        }
                        if (url.StartsWith("https"))
                        {
                            setSetting(beyCooConstants.beyCooHttpsAvailable, "true", web);
                        }
                        if (sslErrors.Length > 0 && !(sslErrors == null))
                        {
                            setSetting(beyCooConstants.beyCooHttpsAvailable, "nottrusted", web);
                        }

                        
                    }
                    catch (Exception e)
                    {
                        beyCooLogger.LogError("beyCooError", e.Message + ", " + e.StackTrace );
                        setSetting(beyCooConstants.beyCooHttpsAvailable, "false", web);
                        
                    }
                    
                    return services;
                }
            }
        }


        private void AddProxy(HttpWebRequest webRequest, SPWeb web)
        {
            WebProxy proxy = new WebProxy();
            string proxyAddress = "";
            int proxyPort = -1;
            string proxyUser = "";
            string proxyPwd = "";
            if (web.Properties.ContainsKey(beyCooConstants.beyCooProxyAddress))
            {
                proxyAddress = web.Properties[beyCooConstants.beyCooProxyAddress].ToString();
            }
            if (web.Properties.ContainsKey(beyCooConstants.beyCooProxyPort))
            {
                proxyPort = Int16.Parse(web.Properties[beyCooConstants.beyCooProxyPort].ToString());
            }

            try
            {
                proxy = new WebProxy(proxyAddress, proxyPort);
            }
            catch (Exception Exc)
            {
                beyCooLogger.LogError("beyCooError", Exc.Message + Exc.StackTrace);
            }


            if (web.Properties.ContainsKey(beyCooConstants.beyCooUseProxyCredentials))
            {
                bool useCredentials = Boolean.Parse(web.Properties[beyCooConstants.beyCooUseProxyCredentials].ToString());
                if (useCredentials)
                {
                    if (web.Properties.ContainsKey(beyCooConstants.beyCooProxyUser))
                    {
                        proxyUser = web.Properties[beyCooConstants.beyCooProxyUser].ToString();
                    }
                    if (web.Properties.ContainsKey(beyCooConstants.beyCooProxyPwd))
                    {
                        proxyPwd = web.Properties[beyCooConstants.beyCooProxyPwd].ToString();
                    }

                    proxy.Credentials = new NetworkCredential(proxyUser, proxyPwd);  
                }
            }
            
            webRequest.Proxy = proxy;
        }

        private void setSetting(string key, string value, SPWeb web)
        {
            web.AllowUnsafeUpdates = true;
            if (!web.Properties.ContainsKey(key))
            {
                web.Properties.Add(key, value);
            }
            else
            {
                web.Properties[key] = value;
            }
            web.Properties.Update();
            web.AllowUnsafeUpdates = false;
        }

    }
}
